import axios from 'axios'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
// import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user' 
import JSONbig from 'json-bigint';
const JSONbigToString = JSONbig({ storeAsString: true })
import Cookies from 'js-cookie'
import { rsaDecrypt, aesDecrypt, aesEncrypt, checkFields, checkTime, checkApi } from "@/tools/encryptionAndDecryption";
// 是否显示重新登录
export let isRelogin = { show: false };

// axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项，表示请求URL公共部分
  baseURL: import.meta.env.VITE_APP_BASE_API,
  // 超时
  timeout: 50000,  //接口请求超时时间
  headers: { 'Content-Type': 'application/json' },
  transformResponse: [function (data) {  // 响应数据进行转换
    try {
      return JSONbig.parse(data)
    } catch (err) {
      return data;
    }

  }], 
})

// request请求拦截器
service.interceptors.request.use(config => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false 
  // 是否需要防止数据重复提交
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  if (getToken() && !isToken) { 
    let tokenType = getToken().slice(0, 5) == 'Basic' ? '' : 'Bearer ' 
    config.headers['Authorization'] = tokenType + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  } 

  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  } 

  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
    } 
    const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
    const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
    if (requestSize >= limitSize) {
      console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制，无法进行防重复提交验证。')
      return config;
    } 
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {
      const s_url = sessionObj.url;                // 请求地址
      const s_data = sessionObj.data;              // 请求数据
      const s_time = sessionObj.time;              // 请求时间
      const interval = 500;                       // 间隔时间(ms)，小于此时间视为重复提交
      // console.log("s_url",s_url,requestObj.url)
      // console.log("time",requestObj.time - s_time)
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        // console.log("s_data",s_data)
        // console.log("s_time", s_time)
        // console.log("s_url", s_url)
        // console.log("requestObj",requestObj)
        const message = '数据正在处理，请勿重复提交';
        // return Promise.reject(new Error(message))
        return Promise.reject(message)
      } else {
        cache.session.setJSON('sessionObj', requestObj)
      } 
    }
  }

  // 接口请求时 对响应字段进行加密  如：身份证号 手机号
  // console.log("请求参数",config)
  let array = config.url.split('/')
  const apiName = array[array.length - 1];
  if(checkApi(apiName)){
    return config
  }else{
    return encryptAESSring(config) || config
  }
}, error => { 
  console.log("ERROR:",error)
  Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(
  res =>{
    // console.log("baseData",res)
    let configUrl = res.config.url.split("/")
    let interfaceName = configUrl[configUrl.length -1]//当前请求的接口名称

    let { data, status,request} = res;
    if (request.responseType === 'blob' || request.responseType === 'arraybuffer') { 
      return res.data
    }
    if(status == 200){
      if(data.code == "00000"){
        const notDecryptionInterface  = ["getAesEncryptKey"]  // 此接口是获取密钥接口  不进行处理
        let afterDecryption = data
        // 接口请求成功后 对加密的字段进行解密 如：身份证号 手机号....
        if(!notDecryptionInterface.includes(interfaceName)){
          data = JSONbig.parse(JSON.stringify(data))
          afterDecryption = decryptAESSring(data)
        }
        return Promise.resolve(afterDecryption)
      }else if(data.code == "A0230"){
        Cookies.remove("Admin-Token")
        if (!isRelogin.show) {
          isRelogin.show = true;
          ElMessageBox.confirm(
            `登录状态已过期，您可以强制刷新页面，或者重新登录`, 
            '系统提示', 
            { 
              // cancelButtonText: '取消1', 
              confirmButtonText: '重新登录', 
              type: 'warning',
              showCancelButton: false, // 不显示取消按钮
              showClose: false, // 禁用关闭按钮
            }).then(() => {
              isRelogin.show = false;
              useUserStore().logOut().then(() => {
                location.href = '/demo/';
              })
            }).catch(() => {
              isRelogin.show = false;
            });
        }
        return Promise.reject('登陆状态发生变化，请重新登录/或刷新页面。')
      }else if(data.code == "B0001"){
        ElMessage({ message: `${data.msg}--907`, type: 'error' })
        return Promise.reject({code:'B0001',msg:data.msg})
      }else{
        ElMessage({ message: `${status}-数据返回失败，请刷新页面-${data.code}--906`, type: 'error' })
        return Promise.reject()
      }
    }else{
      ElMessage({ message: "数据返回失败，请刷新页面--905", type: 'error' })
      return Promise.reject()
    }
  },
  error => {
    console.log("Error",error)
    let { response, message, status} = error;
    const resData = response?.data  || {code:"9999","msg":"无data数据"} // 接口返回数据
    if(status >= 400 &&  status < 500){
      if(resData.code == "B0001"){
        ElMessage({ message: `${resData.msg}--901`, type: 'warning' })
        return Promise.reject(resData.msg)
      }else if(resData.code == "A0230"){  // token 过期（需要让用户重新登录）
        Cookies.remove("Admin-Token")
        if (!isRelogin.show) {
          isRelogin.show = true;
          ElMessageBox.confirm(
            `登录状态已过期，您可以强制刷新页面，或者重新登录`, 
            '系统提示', 
            { 
              // cancelButtonText: '取消1', 
              confirmButtonText: '重新登录', 
              type: 'warning',
              showCancelButton: false, // 不显示取消按钮
              showClose: false, // 禁用关闭按钮
            }).then(() => {
              isRelogin.show = false;
              useUserStore().logOut().then(() => {
                const pathname = Cookies.get('pathname')
                location.href = pathname;
            })
          }).catch(() => {
            isRelogin.show = false;
          });
        }
        return Promise.reject(resData.msg)
      }else{
        ElMessage({ message: `${resData.msg}--902`, type: 'warning' })
        return Promise.reject(new Error(resData.msg))
      }
    }else if(status >= 500) {
      ElMessage({ message: `${status}服务端异常--903`, type: 'warning' }) 
      return Promise.reject(message)
    }else{
      ElMessage({ message: `${status}网络异常--904`, type: 'warning' })
      return Promise.reject(message)
    }
  }
)

function decryptAESSring(obj) { // 递归 解密obj中的加密串
  if (Array.isArray(obj)) {
    return obj.map(item => decryptAESSring(item));
  }else if (typeof obj === 'object' && obj !== null) {
    const result = {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        const value = obj[key];
        if(typeof value == "string" && checkFields(key)){
          const decryptInfo = JSON.parse(Cookies.get('decryptInfo'))
          if(decryptInfo){
            const aesKey =  rsaDecrypt(decryptInfo.secretKey,decryptInfo.privateKey)
            const aesIV = rsaDecrypt(decryptInfo.secretIv,decryptInfo.privateKey)
            result[key] = aesDecrypt(value,aesKey,aesIV)
          }else{
            result[key] = value
          }
        }else {
          result[key] = decryptAESSring(value);
        }
     
      }
    }
    return result;
  }else if(typeof obj === 'string' && obj !== null){
    try{
      const parsed = JSON.parse(obj);
      if(typeof parsed === 'number'){
        return obj;
      }else{
        const processed = decryptAESSring(parsed); // 递归处理解析后的对象
        return JSON.stringify(processed);
      }
    }catch{
      return obj;
    }
  }else if(typeof obj === 'number' && obj !== null){
    return obj;
  }
  return obj;
}


function encryptAESSring(obj) { // 递归 加密obj中需要加密的字符串
  if (Array.isArray(obj)) {
    return obj.map(item => encryptAESSring(item));
  } else if (typeof obj === 'object' && obj !== null) {
    const result = {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        const value = obj[key];
        // typeof Thu Jul 10 2025 00:00:00 GMT+0800 (GMT+08:00) = object 
        if(checkTime(key)){
          result[key] = value
        }else{
          if(value != "" && typeof value == "string" && checkFields(key)){
            const decryptInfo = JSON.parse(Cookies.get('decryptInfo'))
            if(decryptInfo){
              const aesKey =  rsaDecrypt(decryptInfo.secretKey,decryptInfo.privateKey)
              const aesIV = rsaDecrypt(decryptInfo.secretIv,decryptInfo.privateKey)
              result[key] = aesEncrypt(value,aesKey,aesIV)
            }else{
              result[key] = value
            }
          }else {
            result[key] = encryptAESSring(value);
          }
        }
      }
    }
    return result;
  }else if(typeof obj === 'string' && obj !== null){
    try{
      const parsed = JSON.parse(obj);
      const processed = encryptAESSring(parsed); // 递归处理解析后的对象
      return JSON.stringify(processed);
    }catch{
      return obj;
    }
  }
  return obj;
}
// ***
// 系统接口 在入参是 一般会把 Thu Jul 10 2025 00:00:00 GMT+0800 (GMT+08:00) 这种时间格式认为object
// 为了不影响递归算法的使用 需要对此种时间格式进行特殊处理
// **

export default service
